﻿using System;
using System.Collections.Generic;
using System.CodeDom.Compiler;

namespace SWF
{
    public class DefineFunction : IAction, IStackManipulator, IActionContainer
    {
        /*
            FunctionName STRING
            NumParams UI16
            param 1 STRING
            param 2 STRING
            ...
            param N STRING
            codeSize UI16
         */
        public ActionKind ActionId { get { return ActionKind.DefineFunction; } }
        public uint Version { get { return 5; } }
        public uint Length
        {
            get
            {
                uint len = 7;
                len += (uint)FunctionName.Length + 1;
                for (int i = 0; i < Params.Length; i++)
                {
                    len += (uint)Params[i].Length + 1;
                }
                return len;
            }
        }

        public uint StackPops { get { return 0; } }
        public uint StackPushes { get { return 0; } }
        public int StackChange { get { return 0; } }

        private uint codeSize;
        public uint CodeSize { get { return codeSize; } set { codeSize = value; } } // todo: calc code size
        private List<IAction> statements = new List<IAction>();
        public List<IAction> Statements { get { return statements; } }

        public string FunctionName;
        public string[] Params;

        private ConstantPool cp;

        public DefineFunction(SwfReader r, ConstantPool cp)
        {
            this.cp = cp;
            FunctionName = r.GetString();
            uint paramCount = r.GetUI16();
            Params = new string[paramCount];
            for (int i = 0; i < paramCount; i++)
            {
                Params[i] = r.GetString();
            }

            CodeSize = r.GetUI16();
        }

        public void Execute(Runtime.Clip clip, Stack<object> stack, Dictionary<string, object> variables, List<string> constantPool, Dictionary<string, List<IAction>> functionmap)
        {
            functionmap.Add(FunctionName, statements);

            //do not execute here
            //foreach (IAction actionOp in functionmap[FunctionName])
            //{
            //    actionOp.Execute(clip, stack, variables, constantPool, functionmap);
            //}
        }
    }
}
